/**
* @file        log4cplus_impl
* @brief       
* @version     1.0.0
* @author      Changlin.Jing 
* @date        2023/7/27 13:46
* @copyright   Copyright  2022 Langge Software Co., Ltd. All rights reserved.
*/
#include "log4cplus_impl.hpp"
#include "log4cplus/logger.h"
#include "log4cplus/fileappender.h"
#include "log4cplus/consoleappender.h"
#include "log4cplus/layout.h"
#include "log4cplus/loggingmacros.h"
int vdr::Log4cplusImpl::Init(const char *logId, const char *logDir, const char *logFileId,const bool isSyncTerminal) {
    // 入参检测
    if (nullptr == logId)
    {
        return -1;
    }
    if (nullptr == logDir)
    {
        return -2;
    }

    // 如果日志已经存在，则直接返回
    if (log4cplus::Logger::exists(logId))
    {
        log4cplus::Logger logger = log4cplus::Logger::getInstance(logId);
        logger.removeAllAppenders();
    }
    log4cplus::setThreadPoolSize(1);
    // 日志名称
    std::string path(logDir);
    if ('/' != path.at(path.length() - 1))
    {
        path += '/';
    }
//    int64_t nowTimestamp = osGetTickCount();
    const std::string name = path + logId +"_"+logFileId+ ".csv";
    /**
     * 创建文件日志
     */
    // 文件书写器
    log4cplus::SharedAppenderPtr fileAppender(
            new (std::nothrow) log4cplus::FileAppender(
                    name, std::ios_base::app,true, true));
    if (nullptr == fileAppender.get())
    {
        return -3;
    }
    std::string logName = logId;
    logName += ".file.appender";
    fileAppender->setName(logName);
    // 日志格式限定
    const std::string filePattern = "%m%n";
    std::unique_ptr<log4cplus::Layout> patternLayout(
            new (std::nothrow) log4cplus::PatternLayout(filePattern));
    if (nullptr == patternLayout.get())
    {
        return -4;
    }
    fileAppender->setLayout(std::move(patternLayout));
    // 创建文件日志
    log4cplus::Logger logger = log4cplus::Logger::getInstance(logId);
    logger.addAppender(fileAppender);
    /**
    * 终端日志
    */
    if (isSyncTerminal)
    {
        // 终端书写器
        log4cplus::SharedAppenderPtr consoleAppender(
                new (std::nothrow) log4cplus::ConsoleAppender());
        if (nullptr == consoleAppender)
        {
            return -5;
        }
        logName = logId;
        logName += ".console.appender";
        consoleAppender->setName(logName);
        const std::string consolePattern = "%D{%y-%m-%d %H:%M:%S,%Q} [%-5t] [%-5p] [%l] [%M] - %m%n";

        // 日志格式限定
        std::unique_ptr<log4cplus::Layout> consolePatternLayout(
                new (std::nothrow) log4cplus::PatternLayout(consolePattern));
        if (nullptr == consolePatternLayout.get())
        {
            return -6;
        }
        consoleAppender->setLayout(std::move(consolePatternLayout));
        // 增加终端日志
        logger.addAppender(consoleAppender);
    }
    return 0;
}

int
vdr::Log4cplusImpl::WriteLog(const char *logId, const int logLevel, const char *file, const int line, const char *func,
                             const char *content) {
    // 获取Logger
    log4cplus::Logger logger = log4cplus::Logger::getInstance(logId);
    // 书写日志
    LOG4CPLUS_SUPPRESS_DOWHILE_WARNING()
    log4cplus::Logger const &l = log4cplus::detail::macros_get_logger(logger);
    if (l.isEnabledFor(logLevel))
    {
        log4cplus::detail::macro_forced_log(l, logLevel,content, file, line, func);
    }
    LOG4CPLUS_RESTORE_DOWHILE_WARNING()
    return 0;
}

int vdr::Log4cplusImpl::WriteFormatLog(const char *logId, const int logLevel, const char *file, const int line,
                                       const char *func, const char *format, ...) {
    // 入参检测
    if (nullptr == logId)
    {
        return -1;
    }
    if (log4cplus::TRACE_LOG_LEVEL != logLevel &&
        log4cplus::DEBUG_LOG_LEVEL != logLevel &&
        log4cplus::INFO_LOG_LEVEL != logLevel &&
        log4cplus::WARN_LOG_LEVEL != logLevel &&
        log4cplus::ERROR_LOG_LEVEL != logLevel &&
        log4cplus::FATAL_LOG_LEVEL != logLevel)
    {
        return -2;
    }
    if (nullptr == file)
    {
        return -3;
    }
    if (line <= 0)
    {
        return -4;
    }
    if (nullptr == func)
    {
        return -5;
    }
    if (nullptr == format)
    {
        return -7;
    }

    // Logger检测
    if (false == log4cplus::Logger::exists(logId))
    {
        return -8;
    }
    std::string f_msg = format;
    // 获取Logger
    log4cplus::Logger logger = log4cplus::Logger::getInstance(logId);

    // 书写日志
    LOG4CPLUS_SUPPRESS_DOWHILE_WARNING()
    log4cplus::Logger const &l = log4cplus::detail::macros_get_logger(logger);
    if (l.isEnabledFor(logLevel))
    {
        LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(_snpbuf);
        std::va_list args;
        log4cplus::tchar const *logEvent = nullptr;
        int ret = 0;
        do
        {
            va_start(args, format);
            ret = _snpbuf.print_va_list(logEvent, f_msg.c_str(), args);
            va_end(args);
        } while (-1 == ret);
        log4cplus::detail::macro_forced_log(l, logLevel, logEvent, file, line, func);
    }
    LOG4CPLUS_RESTORE_DOWHILE_WARNING()

    // 返回
    return 0;
}
